package com.Example;
import com.Example.Model.Transfer.Transfer;
import com.Example.Model.SupplyType.IPTSignFixed;
import com.Example.Model.SupplyType.IPTSignShare;
import com.Example.Model.SupplyType.IPTSplit;
import com.Example.Model.SupplyType.ShareRatio;
import com.Example.Model.userInfo;
import com.alibaba.fastjson.JSON;
import com.client.RepChainClient;
import com.google.common.base.Charsets;
import com.google.common.io.Files;
import com.websocket.wsCallBack;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.io.FileUtils;
import com.alibaba.fastjson.JSONObject;
import com.protos.Peer.*;


import java.io.*;
import java.util.*;

import org.apache.commons.codec.binary.Hex;  // apache 的编码解码包


public class Commit implements wsCallBack {
    public static void main(String[] args) {
        String str_trans = "";
        String str_supply = "";
        String pemCer = "";
        String host = "192.168.2.69:8081";
        RepChainClient client = new RepChainClient(host);
        client.setJksPath("jks/mykeystore_1.jks");
        client.setPassword("123");
        client.setAlias("1");
        try {
            str_trans =  Files.asCharSource(new File("Json/transfer_1.json"), Charsets.UTF_8).read(); // google的包,最新的Files.toString()即将废弃
            str_supply = FileUtils.readFileToString(new File("Tpl/SupplyTPL.scala"), Charsets.UTF_8);  // apache commons的包
            pemCer = Files.asCharSource(new File("jks/qz.cer"), Charsets.UTF_8).read();
        } catch (Exception ex) {
            System.out.println(ex.getMessage());
            ex.printStackTrace();
        }
//      pemCrt = X509Factory.BEGIN_CERT + Base64.encodeBase64String(certificate.getEncoded()) + X509Factory.END_CERT;
        byte[] cerBytes = pemCer.getBytes();
        String base64Cer = Base64.encodeBase64String(cerBytes);
        userInfo usrinfo = new userInfo("zyf", "1314122", "123@qq.com");
        String base64Info = Base64.encodeBase64String(JSONObject.toJSONString(usrinfo).getBytes());
        Map usrCer = new HashMap<String, String>();
        usrCer.put(base64Cer, base64Info);

//        Transaction t1 = Transaction.newBuilder().build();
        try {
            String chainCodeId = "3bf632f6262f9e1742b1f12c3992d91c0a2f6e9b7e7d0f65f3fb356a4f398c62";  //这个是给转账交易示范用的，此ID需要与repchain合约部署的一致
            // 构建转账交易1   chainCodeId 是部署好的合约的txid；
           Transaction transfer = client.createTransaction(Transaction.Type.CHAINCODE_INVOKE, "path",
                    "transfer" ,str_trans,"string", chainCodeId,ChaincodeSpec.CodeType.CODE_SCALA);
            byte[] bytes = transfer.toByteArray();
            String transferstr = Hex.encodeHexString(bytes);
            // 构建转账交易2
            Transfer trans = new Transfer();  // 也可以直接用构造函数进行构造 new Transfer("st","st","int")
            trans.setFrom("1MH9xedPTkWThJUgT8ZYehiGCM7bEZTVGN");
            trans.setTo("12kAzqqhuq7xYgm9YTph1b9zmCpZPyUWxf");
            trans.setAmount(5);
            Transaction transfer1 = client.createTransaction(Transaction.Type.CHAINCODE_INVOKE, "path",
                    "transfer" ,JSON.toJSONString(trans),"string", chainCodeId,ChaincodeSpec.CodeType.CODE_SCALA);
            //将交易数据post过去
            JSONObject transferResult = client.postTranByString(JSONObject.toJSONString(transferstr));
//            JSONObject transferResult = doPost("http://192.168.2.69:8081/transaction/postTranByString", '"'+transferstr+'"');
            //注册用户证书
            Transaction signUpCer = client.createTransaction(Transaction.Type.CHAINCODE_INVOKE, "path",
                    "signup" ,JSON.toJSONString(usrCer),"string", chainCodeId,ChaincodeSpec.CodeType.CODE_SCALA);
            String signUpCerStr = Hex.encodeHexString(signUpCer.toByteArray());
            JSONObject signupResult = client.postTranByString(JSON.toJSONString(signUpCerStr));

            //部署分账合约
            Transaction SupplyTpl = client.createTransaction(Transaction.Type.CHAINCODE_DEPLOY, "path",
                    "", "", str_supply, "", ChaincodeSpec.CodeType.CODE_SCALA);
            String supplyTplstr = Hex.encodeHexString(SupplyTpl.toByteArray());
            JSONObject tplDeployResult = client.postTranByString(JSON.toJSONString(supplyTplstr));  //   部署分账模板合约
            //TODO 调用分账合约
            String cname = SupplyTpl.getPayload().getChaincodeID().getName();
            Map<String,Double> fm = new HashMap<>();
            fm.put("A",0.2);
            fm.put("B",0.2);
            fm.put("C",0.1);
            fm.put("D",0.1);
            Map<String, ShareRatio[]> sm = new HashMap<>();
            ShareRatio[] shareRatios = new ShareRatio[]{new ShareRatio(0,100,0.1,0),new ShareRatio(100,10000,0.15,0)};
            sm.put("A",shareRatios);
            sm.put("B",new ShareRatio[]{new ShareRatio(0,10000,0,10)});
            sm.put("C",new ShareRatio[]{new ShareRatio(0,10000,0.1,0)});
            sm.put("D",new ShareRatio[]{new ShareRatio(0,100,0,10), new ShareRatio(100,10000,0.15,0)});
            String account_remain = "R";
            String account_sales1 = "S1";
            String account_sales2 = "S2";
            String product_id = "P201806270001";
            //构造签约交易合约模版1输入json字符串，销售1选择了合约模版1
            IPTSignFixed signfm = new IPTSignFixed(account_sales1,product_id,account_remain,fm);
            String signfmstr = JSONObject.toJSONString(signfm);//JSON.toJSONString(ipt2);
            //构造签约交易合约模版2输入json字符串，，销售2选择了合约模版2
            IPTSignShare signsm = new IPTSignShare(account_sales2,product_id,account_remain,sm);
            String signsmstr = JSON.toJSONString(signsm);
            Transaction signfmTran = client.createTransaction(Transaction.Type.CHAINCODE_INVOKE, "path",
                    "SignFixed", signfmstr, "string", cname, ChaincodeSpec.CodeType.CODE_SCALA);
            String fmTranstr = Hex.encodeHexString(signfmTran.toByteArray());
            JSONObject signfmResult = client.postTranByString(JSON.toJSONString(fmTranstr));  //   部署模板1
            Transaction signsmTran = client.createTransaction(Transaction.Type.CHAINCODE_INVOKE,"path",
                    "SignShare", signsmstr, "string", cname, ChaincodeSpec.CodeType.CODE_SCALA);
            String smTranstr = Hex.encodeHexString(signsmTran.toByteArray());
            JSONObject signsmResult = client.postTranByString(JSON.toJSONString(smTranstr));  //   部署模板2
            //TODO 测试各种金额下的分账结果
            int[] sr = new int[]{100, 200, 500, 1000};
            for (int el:sr) {
                //构造分账交易
                IPTSplit ips1 = new IPTSplit(account_sales1,product_id,el);
                IPTSplit ips2 = new IPTSplit(account_sales2,product_id,el);
                String l4 = JSON.toJSONString(ips1);
                String l5 = JSON.toJSONString(ips2);
                try {
                    //调用模板1进行分账
                    Transaction s1Split = client.createTransaction(Transaction.Type.CHAINCODE_INVOKE,"path",
                            "Split", l4, "string", cname, ChaincodeSpec.CodeType.CODE_SCALA);
                    //调用模板2进行分账
                    Transaction s2Split = client.createTransaction(Transaction.Type.CHAINCODE_INVOKE,"path",
                            "Split", l5, "string", cname, ChaincodeSpec.CodeType.CODE_SCALA);
                    String s1Splitstr = Hex.encodeHexString(s1Split.toByteArray());
                    String s2Splitstr = Hex.encodeHexString(s2Split.toByteArray());
                    //  提交交易
                    JSONObject s1SplitResult = client.postTranByString(JSON.toJSONString(s1Splitstr));
//                    JSONObject s2SplitResult = client.postTranByString(JSON.toJSONString(s2Splitstr));
                    // 下面是用来测试回调方法的
                    client.postTranByString(new Commit(), JSON.toJSONString(s2Splitstr), s2Split);
                    // 将分账后的结果映射为Map,从而可以判断分账和
                    // 3种方式都可以构造Map
                    Map s1result = JSONObject.toJavaObject(s1SplitResult.getJSONObject("result"),Map.class);
                    Map result1 = s1SplitResult.getJSONObject("result").getInnerMap();
                    Map result2 = s1SplitResult.getJSONObject("result");
                    int num = 0;
                    for (Object value : s1result.values()) {
                        num += (int)value;
                    }
//                    Map s2result = s2SplitResult.getJSONObject("result");
//                    int num1 = 0;
//                    for (Object value : s2result.values()) {
//                        num1 += (int)value;
//                    }
//                    System.out.println(num == el);
//                    System.out.println(num1 == el);
//                    System.out.println(num);
//                    System.out.println(num1);
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            }
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
    }

    /**
     *
     * @param flag
     * @param result 预执行结果
     */
    @Override
    public void preDoTransaction(Boolean flag, JSONObject result) {
        System.out.println(result);
    }

    /**
     *
     * @param flag
     * @param block
     * @param result
     */
    @Override
    public void verifyBlock(Boolean flag, Block block, String result) {
        System.out.println(block);
        System.out.println(result);
    }
}
